
Imports System.Windows.Forms
Imports System.Drawing
Imports std

Public MustInherit Class outmgrBase(Of c As Control)

    Public out As c

    Protected Friend MustOverride Function setforecolor(ByRef c As Int32) As Boolean
    Protected Friend MustOverride Function setbackcolor(ByRef c As Int32) As Boolean
    Protected Friend MustOverride Function setmaxlength(ByRef l As Int32) As Boolean
    Protected Friend MustOverride Function setfontfamily(ByRef s As String) As Boolean
    Protected Friend MustOverride Function setfontsize(ByRef l As Single) As Boolean

    Public Class def
        Public Const idletime As Double = 100
    End Class

    Protected Friend WithEvents _timer As System.Windows.Forms.Timer
    Protected Friend _buff As circle(Of Char)
    Public idletime As Double

    Public ReadOnly Property buff() As circle(Of Char)
        Get
            Return _buff
        End Get
    End Property

    Public ReadOnly Property timer() As System.Windows.Forms.Timer
        Get
            Return _timer
        End Get
    End Property

    Public Overridable Function output(ByVal s As String) As Boolean
        SyncLock _buff
            assert(_buff.push_back(s.ToCharArray(), 0, -1, True), "_buff.push() returns false.")
        End SyncLock
        Return True
    End Function

    Protected Overridable Sub initial()
        idletime = def.idletime
        _timer = New System.Windows.Forms.Timer
        _timer.Enabled = False
        _buff = New circle(Of Char)
        invokeMethod = AddressOf invokeMethodImpl
    End Sub

    Public Sub New()
        initial()
    End Sub

    Public Sub New(ByVal output As c)
        initial()
        out = output
    End Sub

    Public Sub New(ByVal sleeptime As Double)
        initial()
        idletime = sleeptime
    End Sub

    Public Sub New(ByVal output As c, ByVal sleeptime As Double)
        initial()
        out = output
        idletime = sleeptime
    End Sub

    Public Overridable Function start() As Boolean
        assert(Not out Is Nothing, "no output control existing")
        _timer.Interval = idletime
        _timer.Enabled = True

        Return True
    End Function

    Public Overridable Sub [stop]()
        _timer.Enabled = False
    End Sub

    Public Sub restart()
        [stop]()
        start()
    End Sub

    Public Delegate Sub invokeDelegate(ByVal s As String)
    Public invokeMethod As invokeDelegate

    Protected Overridable Sub invokeMethodImpl(ByVal s As String)
        On Error Resume Next
        out.Text += s
        Dim c As Int32
        Dim col As Color = Nothing
        If setforecolor(c) Then
            col = Color.FromArgb(c)
            If Not out.ForeColor = col Then
                out.ForeColor = col
            End If
        End If

        If setbackcolor(c) Then
            col = Color.FromArgb(c)
            If Not out.BackColor = col Then
                out.BackColor = col
            End If
        End If

        If setmaxlength(c) Then
            If out.Text.Length > c * 1.5 Then
                out.Text = out.Text.Substring(out.Text.Length - c)
            End If
        End If

        Dim str As String = Nothing
        Dim sing As Single
        If setfontfamily(str) AndAlso setfontsize(sing) Then
            Dim fnt As Drawing.Font = New Drawing.Font(str, sing, FontStyle.Regular)
            If Not out.Font.Equals(fnt) Then
                out.Font = fnt
            End If
        End If

        Application.DoEvents()
    End Sub

    Private Sub _timer_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles _timer.Tick
        assert(Not out Is Nothing, "no output control, but passed check in start()?")
        Dim buff() As Char = Nothing
        If Not _buff.empty() Then
            SyncLock _buff
                If Not _buff.empty() Then
                    _buff.pop_front(buff)
                End If
            End SyncLock
            out.Invoke(invokeMethod, New String(buff))
            Application.DoEvents()
        End If
    End Sub
End Class
